package com.file.parser;

import com.file.bo.ResponseData;
import com.file.bo.TJBDC;
import com.file.constant.ErrorCode;
import com.file.util.JsonUtils;
import javafx.util.Pair;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.pdfbox.pdmodel.PDDocument;
import technology.tabula.*;
import technology.tabula.detectors.NurminenDetectionAlgorithm;
import technology.tabula.detectors.SpreadsheetDetectionAlgorithm;
import technology.tabula.extractors.SpreadsheetExtractionAlgorithm;

import java.io.File;
import java.util.*;

import static org.apache.poi.ss.usermodel.Sheet.FooterMargin;

/**
 * 天津不动产pdf解析
 * @author anyspa
 */

@Slf4j
public class TJBDCPdfParser extends BasePdfParser {

    public ResponseData<String> parseTJBDCPdfToJson(String daId, String filePath) {
        log.info("parseTJBDCPdfToJson started, daId:{}", daId);
        String json = null;

        try {
            TJBDC tjbdc = parseTJBDCPdf(filePath);
            json = JsonUtils.convertObjectToJson(tjbdc);
        } catch (Exception e) {
            log.error("OnError|{}||{}|{}|{}|{}", ErrorCode.FILE_PARSE_EXCEPTION.getCode(), daId, "", "", "parseTJBDCPdfToJson failed", e);
            return new ResponseData<>(json, ErrorCode.FILE_PARSE_EXCEPTION.getCode(), ErrorCode.FILE_PARSE_EXCEPTION.getMsg());
        }

        log.info("parseTJBDCPdfToJson completed, daId:{}", daId);
        return new ResponseData<>(json, ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg());
    }

    private TJBDC parseTJBDCPdf(String filePath) {
        // return parseTJBDC(filePath, tjbdc);
        List<List<String>> rowList = parseFileToRowList(filePath);
        return parseTJBDC(rowList);
    }

    private List<List<String>> parseFileToRowList(String filePath) {
        // 1. 读取文件
        File pdf = new File(filePath);

        //页面所有table的记录，每一个元素代表下面一条记录cellList
        List<List<String>> rowList = new ArrayList<>();

        // 2. pdfbox读取PDDocument
        try (PDDocument pdfDocument = PDDocument.load(pdf)) {
            // 3. tabula新建ObjectExtractor和NurminenDetectionAlgorithm，同时准备接收表格Rectangle的结构
            ObjectExtractor objectExtractor = new ObjectExtractor(pdfDocument);
            SpreadsheetDetectionAlgorithm detectionAlgorithm = new SpreadsheetDetectionAlgorithm();
            Map<Integer, List<Rectangle>> pageNumber2RectangleListMap = new HashMap<>();//key为页的序号， value为对应的Rectangle的list

            // 4. 获取每页的PageIterator
            PageIterator pageIterator = objectExtractor.extract();

            // 5. 解析每页的Rectangle
            // 如果单页pdf中有多个Rectangle，则解析出来的List<Rectangle>会有多个对象
            while (pageIterator.hasNext()) {
                Page page = pageIterator.next();
                List<Rectangle> rectangleList = detectionAlgorithm.detect(page);
                if (rectangleList.size() > 0) {
                    pageNumber2RectangleListMap.put(page.getPageNumber(), rectangleList);
                }
            }

            // 6.通过table位置获取表格具体内容
            SpreadsheetExtractionAlgorithm extractionAlgorithm = new SpreadsheetExtractionAlgorithm();

            // 如果单页pdf中有多个表格，则解析出来的List<Rectangle>会有多个对象
            for (Map.Entry<Integer, List<Rectangle>> entry : pageNumber2RectangleListMap.entrySet()) {
                Page page = objectExtractor.extract(entry.getKey());
                Rectangle rectangle = null;

                List<Rectangle> rectangleList = entry.getValue();
                for (Rectangle r : rectangleList) {
                    double rectangleHeight = r.getHeight();
                    if (Double.compare(rectangleHeight, 0) > 0) {
                        rectangle = r;
                        break;
                    }
                }
                if (rectangle == null) {
                    throw new RuntimeException("rectangle is null.");
                }

                rectangle.setBottom(rectangle.getBottom() + FooterMargin);
                Page area = page.getArea(rectangle);

                // 如果每页有多个表格，解析每一个table
                List<Table> tableList = extractionAlgorithm.extract(area);
                for (Table table : tableList) {
                    for (int i = 0; i < table.getRowCount(); i++) {
                        List<String> cellList = new ArrayList<>();//一条记录，每个单元格占一个元素
                        for (int j = 0; j < table.getColCount(); j++) {
                            cellList.add(table.getCell(i, j).getText(false));
                        }
                        rowList.add(cellList);
                    }
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }

        return rowList;
    }

    private TJBDC parseTJBDC(List<List<String>> rowList) {
        TJBDC tjbdc = new TJBDC();
        List<TJBDC.LandRegistrationInfo> landRegistrationInfoList = new ArrayList<>();
        List<TJBDC.HouseRegistrationInfo> houseRegistrationInfoList = new ArrayList<>();
        List<TJBDC.ForestLandRegistrationInfo> forestLandRegistrationInfoList = new ArrayList<>();
        List<TJBDC.SeaAreaInfo> seaAreaInfoList = new ArrayList<>();
        List<TJBDC.MortgageRegistrationInfo> mortgageRegistrationInfoList = new ArrayList<>();
        List<TJBDC.EasementRegistrationInfo> easementRegistrationInfoList = new ArrayList<>();
        List<TJBDC.PreviewRegistrationInfo> previewRegistrationInfoList = new ArrayList<>();
        List<TJBDC.SealUpRegistrationInfo> sealUpRegistrationInfoList = new ArrayList<>();
        List<TJBDC.ObjectionRegistrationInfo> objectionRegistrationInfoList = new ArrayList<>();
        List<TJBDC.OtherInfo> otherInfoList = new ArrayList<>();

        String sectionName = "";

        for (int i = 0; i < rowList.size(); i++) {
            List<String> cellList = rowList.get(i);
            if (StringUtils.equals(cellList.get(0).replaceAll(" ", ""), "权利人") && StringUtils.isBlank(tjbdc.getObligee())) {
                sectionName = "权利人";
            } else if (StringUtils.equals(cellList.get(0), "共有情况")) {
                sectionName = "共有情况";
            } else if (StringUtils.equals(cellList.get(0).replaceAll(" ", ""), "坐落")) {
                sectionName = "坐落";
            } else if (StringUtils.equals(cellList.get(0), "不动产单元号")) {
                sectionName = "不动产单元号";
            } else if (StringUtils.equals(cellList.get(0), "权利类型")) {
                sectionName = "权利类型";
            } else if (StringUtils.equals(cellList.get(0), "登记日期") && StringUtils.isBlank(tjbdc.getRegistrationDate())) {
                sectionName = "登记日期";
            } else if (StringUtils.equals(cellList.get(0), "不动产权证号")) {
                sectionName = "不动产权证号";
            } else if (StringUtils.contains(cellList.get(0), "动产登记证明号")) {
                sectionName = "不动产登记证明号";
            } else if (StringUtils.equals(cellList.get(0).replaceAll(" ", ""), "土地(非林地)登记信息")) {
                sectionName = "土地(非林地)登记信息";
                continue;
            } else if (StringUtils.equals(cellList.get(0).replaceAll(" ", ""), "房屋(构筑物)等登记信息")) {
                sectionName = "房屋(构筑物)等登记信息";
                continue;
            } else if (StringUtils.equals(cellList.get(0).replaceAll(" ", ""), "林地(森林、林木)登记信息")) {
                sectionName = "林地(森林、林木)登记信息";
                continue;
            } else if (StringUtils.equals(cellList.get(0).replaceAll(" ", ""), "海域信息")) {
                sectionName = "海域信息";
                continue;
            } else if (StringUtils.equals(cellList.get(0).replaceAll(" ", ""), "抵押权登记信息")) {
                sectionName = "抵押权登记信息";
                continue;
            } else if (StringUtils.equals(cellList.get(0).replaceAll(" ", ""), "地役权登记信息")) {
                sectionName = "地役权登记信息";
                continue;                                                                     // 预告登记信息
            } else if (StringUtils.equals(cellList.get(0).replaceAll(" ", ""), "预告登记信息")) {
                sectionName = "预告登记信息";
                continue;
            } else if (StringUtils.equals(cellList.get(0).replaceAll(" ", ""), "查封登记信息")) {
                sectionName = "查封登记信息";
                continue;
            } else if (StringUtils.equals(cellList.get(0).replaceAll(" ", ""), "异议登记信息")) {
                sectionName = "异议登记信息";
                continue;
            } else if (StringUtils.equals(cellList.get(0).replaceAll(" ", ""), "其他信息")) {
                sectionName = "其他信息";
                continue;
            }

            switch (sectionName) { //NOSONAR
                case "权利人":
                    tjbdc.setObligee(cellList.get(1));
                    break;
                case "共有情况":
                    tjbdc.setCoOwnership(cellList.get(1));
                    break;
                case "坐落":
                    tjbdc.setLocation(cellList.get(1));
                    break;
                case "不动产单元号":
                    tjbdc.setRealEstateUnitNo(cellList.get(1));
                    break;
                case "权利类型":
                    tjbdc.setRightType(cellList.get(1));
                    break;
                case "登记日期":
                    tjbdc.setRegistrationDate(cellList.get(1));
                    break;
                case "不动产权证号":
                    tjbdc.setRealEstateOwnershipCertificateNo(cellList.get(1));
                    break;
                case "不动产登记证明号":
                    tjbdc.setRealEstateRegistrationCertificateNo(cellList.get(1));
                    break;
                case "土地(非林地)登记信息":
                    if (cellList.get(0).equals("权利性质")) {
                        TJBDC.LandRegistrationInfo landRegistrationInfo = new TJBDC.LandRegistrationInfo();
                        landRegistrationInfo.setNatureOfRights(rowList.get(i + 1).get(0));
                        landRegistrationInfo.setArea(rowList.get(i + 1).get(1));
                        landRegistrationInfo.setServiceLife(rowList.get(i + 1).get(2));
                        landRegistrationInfo.setUse(rowList.get(i + 1).get(3));
                        landRegistrationInfoList.add(landRegistrationInfo);
                        i++;
                    }
                    break;
                case "房屋(构筑物)等登记信息":
                    if (cellList.get(0).equals("幢(房)号")) {
                        TJBDC.HouseRegistrationInfo houseRegistrationInfo = new TJBDC.HouseRegistrationInfo();
                        houseRegistrationInfo.setBuildingNo(rowList.get(i + 1).get(0));
                        houseRegistrationInfo.setHouseStructure(rowList.get(i + 1).get(1));
                        houseRegistrationInfo.setTotalFloors(rowList.get(i + 1).get(2));
                        houseRegistrationInfo.setFloor(rowList.get(i + 1).get(3));
                        houseRegistrationInfo.setPlannedUse(rowList.get(i + 1).get(4));
                        houseRegistrationInfo.setFloorArea(rowList.get(i + 1).get(5));
                        houseRegistrationInfo.setBuildingType(rowList.get(i + 1).get(6));
                        houseRegistrationInfoList.add(houseRegistrationInfo);
                        i++;
                    }
                    break;
                case "林地(森林、林木)登记信息":
                    if (cellList.get(0).equals("面积(亩)")) {
                        TJBDC.ForestLandRegistrationInfo forestLandRegistrationInfo = new TJBDC.ForestLandRegistrationInfo();
                        forestLandRegistrationInfo.setArea(rowList.get(i + 1).get(0));
                        forestLandRegistrationInfo.setServiceLife(rowList.get(i + 1).get(1));
                        forestLandRegistrationInfo.setMainTrees(rowList.get(i + 1).get(2));
                        forestLandRegistrationInfo.setTreeCount(rowList.get(i + 1).get(3));
                        forestLandRegistrationInfo.setToponymy(rowList.get(i + 1).get(4));
                        forestLandRegistrationInfo.setForestClass(rowList.get(i + 1).get(5));
                        forestLandRegistrationInfo.setSmallClass(rowList.get(i + 1).get(6));
                        forestLandRegistrationInfoList.add(forestLandRegistrationInfo);
                        i++;
                    }
                    break;
                case "海域信息":
                    if (cellList.get(0).equals("项目名称")) {
                        TJBDC.SeaAreaInfo seaAreaInfo = new TJBDC.SeaAreaInfo();
                        seaAreaInfo.setProjectName(rowList.get(i + 1).get(0));
                        seaAreaInfo.setNatureOfProject(rowList.get(i + 1).get(1));
                        seaAreaInfo.setServiceLife(rowList.get(i + 1).get(2));
                        seaAreaInfo.setSeaUseType(rowList.get(i + 1).get(3));
                        seaAreaInfo.setAreaOfSeaUse(rowList.get(i + 1).get(4));
                        seaAreaInfo.setSeaUseMode(rowList.get(i + 1).get(5));
                        seaAreaInfoList.add(seaAreaInfo);
                        i++;
                    }
                    break;
                case "抵押权登记信息":
                    if (cellList.get(0).equals("登记日期")) {
                        TJBDC.MortgageRegistrationInfo mortgageRegistrationInfo = new TJBDC.MortgageRegistrationInfo();
                        mortgageRegistrationInfo.setRegistrationDate(rowList.get(i).get(1));
                        mortgageRegistrationInfo.setRealEstateRegistrationCertificateNo(rowList.get(i).get(3));
                        mortgageRegistrationInfo.setMortgagor(rowList.get(i + 1).get(1));
                        mortgageRegistrationInfo.setMortgagee(rowList.get(i + 2).get(1));
                        mortgageRegistrationInfo.setMortgageScope(rowList.get(i + 3).get(1));
                        mortgageRegistrationInfo.setSecuredPrincipalClaimAmount(rowList.get(i + 4).get(1));
                        mortgageRegistrationInfo.setDebtPerformancePeriod(rowList.get(i + 4).get(3));
                        mortgageRegistrationInfoList.add(mortgageRegistrationInfo);
                        i += 4;
                    }
                    break;
                case "地役权登记信息":
                    if (cellList.get(0).equals("登记日期")) {
                        TJBDC.EasementRegistrationInfo easementRegistrationInfo = new TJBDC.EasementRegistrationInfo();
                        easementRegistrationInfo.setRegistrationDate(rowList.get(i).get(1));
                        easementRegistrationInfo.setRealEstateRegistrationCertificateNo(rowList.get(i).get(3));
                        easementRegistrationInfo.setEasementHolder(rowList.get(i + 1).get(1));
                        easementRegistrationInfo.setEasementContent(rowList.get(i + 1).get(3));
                        easementRegistrationInfo.setServileLandLocated(rowList.get(i + 2).get(1));
                        easementRegistrationInfo.setServileLandRealEstateUnitNo(rowList.get(i + 2).get(3));
                        easementRegistrationInfoList.add(easementRegistrationInfo);
                        i += 2;
                    }
                    break;
                case "预告登记信息":
                    if (cellList.get(0).equals("登记日期")) {
                        TJBDC.PreviewRegistrationInfo previewRegistrationInfo = new TJBDC.PreviewRegistrationInfo();
                        previewRegistrationInfo.setRegistrationDate(rowList.get(i).get(1));
                        previewRegistrationInfo.setRealEstateRegistrationCertificateNo(rowList.get(i).get(3));
                        previewRegistrationInfo.setPreviewRegistrationType(rowList.get(i + 1).get(1));
                        previewRegistrationInfo.setFloorArea(rowList.get(i + 1).get(3));
                        previewRegistrationInfo.setObligee(rowList.get(i + 2).get(1));
                        previewRegistrationInfo.setObligor(rowList.get(i + 2).get(3));
                        previewRegistrationInfo.setSecuredClaimAmount(rowList.get(i + 3).get(1));
                        previewRegistrationInfo.setDebtPerformancePeriod(rowList.get(i + 3).get(3));
                        previewRegistrationInfoList.add(previewRegistrationInfo);
                        i += 3;
                    }
                    break;
                case "查封登记信息":
                    if (cellList.get(0).equals("查封机关")) {
                        TJBDC.SealUpRegistrationInfo sealUpRegistrationInfo = new TJBDC.SealUpRegistrationInfo();
                        sealUpRegistrationInfo.setSealUpAuthority(rowList.get(i).get(1));
                        sealUpRegistrationInfo.setSealUpType(rowList.get(i).get(3));
                        sealUpRegistrationInfo.setSealUpDate(rowList.get(i + 1).get(1));
                        sealUpRegistrationInfo.setSealUpDocument(rowList.get(i + 1).get(3));
                        sealUpRegistrationInfo.setSealUpPeriod(rowList.get(i + 2).get(1));
                        sealUpRegistrationInfoList.add(sealUpRegistrationInfo);
                        i += 2;
                    }
                    break;
                case "异议登记信息":
                    if (cellList.get(0).equals("申请人")) {
                        TJBDC.ObjectionRegistrationInfo objectionRegistrationInfo = new TJBDC.ObjectionRegistrationInfo();
                        objectionRegistrationInfo.setApplicant(rowList.get(i).get(1));
                        objectionRegistrationInfo.setRegistrationDate(rowList.get(i).get(3));
                        objectionRegistrationInfo.setObjectionItem(rowList.get(i + 1).get(1));
                        objectionRegistrationInfoList.add(objectionRegistrationInfo);
                        i++ ;
                    }
                    break;
                case "其他信息":
                    if (cellList.get(0).equals("记载日期")) {
                        TJBDC.OtherInfo otherInfo = new TJBDC.OtherInfo();
                        otherInfo.setRecordDate(rowList.get(i).get(1));
                        otherInfo.setRecordItem(rowList.get(i).get(3));
                        otherInfoList.add(otherInfo);
                    }
                    break;
            }
        }

        tjbdc.setLandRegistrationInfos(landRegistrationInfoList);
        tjbdc.setHouseRegistrationInfos(houseRegistrationInfoList);
        tjbdc.setForestLandRegistrationInfos(forestLandRegistrationInfoList);
        tjbdc.setSeaAreaInfos(seaAreaInfoList);
        tjbdc.setMortgageRegistrationInfos(mortgageRegistrationInfoList);
        tjbdc.setEasementRegistrationInfos(easementRegistrationInfoList);
        tjbdc.setPreviewRegistrationInfos(previewRegistrationInfoList);
        tjbdc.setSealUpRegistrationInfos(sealUpRegistrationInfoList);
        tjbdc.setObjectionRegistrationInfos(objectionRegistrationInfoList);
        tjbdc.setOtherInfos(otherInfoList);

        return tjbdc;
    }

    public static void main(String[] args) {
        TJBDCPdfParser tjbdcPdfParser = new TJBDCPdfParser();
        String json = tjbdcPdfParser.parseTJBDCPdfToJson("", "D:\\data\\files\\TJBDC\\zd1zl4kd1570941286469582848_d683a39e9c8bb0ecc0ed326fc9f85368_chrome-tjbdc_bdcsj1.pdf").getData();
        System.out.println(json);

        json = tjbdcPdfParser.parseTJBDCPdfToJson("", "D:\\data\\files\\TJBDC\\zd1tuknz1572143067383971840_820fa6bc96d06906326d0d86f8d4c0c8_chrome-tjbdc_bdcsj1.pdf").getData();
        System.out.println(json);

        json = tjbdcPdfParser.parseTJBDCPdfToJson("", "D:\\data\\files\\TJBDC\\zd1tuknz1572143067383971840_256eda701f2f3527e175e495f0270bbe_chrome-tjbdc_bdcsj2.pdf").getData();
        System.out.println(json);
    }
}
